package de.lang.rollo.controller.logic;

import java.util.ArrayList;
import java.util.List;

import org.mongojack.JacksonDBCollection;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.pi4j.io.gpio.Pin;

import de.lang.rollo.controller.configurations.GpioConfiguration;
import de.lang.rollo.controller.enums.MotorState;
import de.lang.rollo.controller.enums.SchalterType;
import de.lang.rollo.controller.managed.MongoManaged;
import de.lang.rollo.controller.model.RolloEvent;
import de.lang.rollo.controller.model.RolloMotor;
import de.lang.rollo.controller.model.Schalter;
import de.lang.rollo.controller.model.daos.MotorDAO;
import de.lang.rollo.controller.model.daos.SchalterDAO;

public class GPIOFactory {
	private static Logger logger = LoggerFactory.getLogger(GPIOFactory.class);

	private static GPIOFacade facade;
	private static long alleBedienen;
	private static boolean reset;
	private static GpioConfiguration config;

	public static GPIOFacade getFacade() {
		return facade;
	}

	public static GPIOFacade refreshFacade() {
		if (facade != null)
			facade.shutdown();
		SchalterDAO schalterDAO = new SchalterDAO();
		facade = new GPIOFacade(schalterDAO.getAllSchalter(), config
				.getPinConfiguration().getAlleBedienenPressDiff(), config.getRunningOnPi());
		return facade;
	}

	public static GPIOFacade createFacade(GpioConfiguration config) {
		GPIOFactory.config = config;
		SchalterDAO schalterDAO = new SchalterDAO();
		List<Schalter> sList = null;
		List<RolloMotor> mList = null;
		sList = schalterDAO.getAllSchalter();

		if (config.getPinConfiguration().getOverWriteConfig()
				|| sList.size() == 0) {
			logger.info("Using yml File for Pin Configuration");
			MongoManaged.dropAll();

			mList = new ArrayList<RolloMotor>();
			List<Pin> mHelper = config.getPinConfiguration().getMotorenPins();
			List<Long> runTimeHelper = config.getPinConfiguration()
					.getMotorenPinRunTimes();
			List<String> nHelper = config.getPinConfiguration()
					.getMotorenNamen();
			sList = new ArrayList<Schalter>();
			List<Pin> schalterHelper = config.getPinConfiguration()
					.getSchalterPins();
			if (mHelper.size() % 2 == 0) {
				// logger.info("Adding " + mHelper.size() / 2 + " Motoren, "
				// + schalterHelper.size() + " Schalter and "
				// + nHelper.size() + " Motor-Namen.");
				RolloMotor motor = null;
				logger.info("Motoren: " + mHelper.size() + " Timer: "
						+ runTimeHelper.size() + " Schalter: "
						+ schalterHelper.size());
				int i = 0;
				while (i < mHelper.size()) {
					logger.info("Current i: " + i);
					logger.info("PinUp: " + mHelper.get(i).getName()
							+ "PinDown: " + mHelper.get(i + 1).getName());
					motor = new RolloMotor();
					motor.setPinUp(mHelper.get(i));
					motor.setPinDown(mHelper.get(i + 1));

					// motor.setRunTimeUp(runTimeHelper.get(i));
					// motor.setRunTimeDown(runTimeHelper.get(i + i));
					motor.setRunTimeUp(runTimeHelper.get(0));
					motor.setRunTimeDown(runTimeHelper.get(1));

					if (i % 2 == 0)
						motor.setName(nHelper.get((int) (i / 2.0)));
					else
						motor.setName(nHelper.get((int) (i / 2.0 - 0.5)));

					motor.setState(MotorState.UP);
					mList.add(motor);
					// motoren.save(motor);
					Schalter sch = new Schalter();
					sch.setName(motor.getName() + "_sw_up");
					sch.setPin(schalterHelper.get(i));
					sch.setMotor(motor);
					sch.setType(SchalterType.UP);
					// schalter.save(sch);
					sList.add(sch);
					schalterDAO.insertSchalter(sch);

					sch = new Schalter();
					sch.setName(motor.getName() + "_sw_down");
					sch.setPin(schalterHelper.get(i + 1));
					sch.setMotor(motor);
					sch.setType(SchalterType.DOWN);
					// schalter.save(sch);
					sList.add(sch);
					schalterDAO.insertSchalter(sch);

					i = i + 2;
				}
			} else {
				logger.info("Reading Database");
				// return null;
			}
		}
		logger.info("Motor-Count: " + mList.size() + " Schalter-Count: "
				+ sList.size());
		// return new GPIOFacade(schalter.find().toArray(),
		// config.getPinConfiguration().getAlleBedienenPressDiff()); // todo
		// read from db
		facade = new GPIOFacade(sList, config.getPinConfiguration()
				.getAlleBedienenPressDiff(), config.getRunningOnPi());
		return facade;
	}
}
